package com.audaque.springboot.foshanupload.web.redisdemo.controller;

import com.audaque.springboot.foshanupload.web.redisdemo.model.Ur;
import jodd.util.MathUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author zgb
 * RedisTemplate使用的序列类在在操作数据的时候，比如说存入数据会将数据先序列化成字节数组,然后在存入Redis数据库
 * 当Redis当中的数据值是以可读的形式显示出来的时候，只能使用StringRedisTemplate才能获取到里面的数据。
 * 当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候，那么你就使用StringRedisTemplate即可，
 * 但是如果你的数据是复杂的对象类型，而取出的时候又不想做任何的数据转换，直接从Redis里面取出一个对象，那么使用RedisTemplate是
 * 更好的选择。
 */
@Slf4j
@RestController
@RequestMapping("redisOpt")
public class RedisOptController {
    @Autowired
    private ApplicationContext context;

    @Autowired(required = false)
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    @GetMapping("/redisTemplateKeys")
    public void RedisTemplateKeys(String prxfix,String suffix) {
        for (int j = 0; j < 10; j++) {
            stringRedisTemplate.opsForValue().set(prxfix+j+":"+suffix+j, "redis"+j);
        }

        String keyword = prxfix+"*:"+suffix+"*";//这个*一定要加，否则无法模糊查询
        Set<String> keys = stringRedisTemplate.keys(keyword);
        for (String key : keys) {
            System.out.println(key);
        }

        stringRedisTemplate.delete(keys);

    }


    @GetMapping("/redisTemplateTest")
    public void RedisTemplateTest() {
        log.debug(redisTemplate.toString());  // 结果： org.springframework.data.redis.core.RedisTemplate@314c8b4a
        redisTemplate.opsForValue().set("db-type", "redis");
        log.debug(redisTemplate.opsForValue().get("db-type").toString()); // 结果： redis
    }

    @GetMapping("/stringRedisTemplateTest")
    public void StringRedisTemplateTest() {
        log.debug(stringRedisTemplate.toString());  // 结果： org.springframework.data.redis.core.RedisTemplate@314c8b4a
        stringRedisTemplate.opsForValue().set("db-type", "mongodb");
        log.debug(stringRedisTemplate.opsForValue().get("db-type")); // 结果： mongodb
        log.debug(redisTemplate.opsForValue().get("db-type").toString()); // 结果： redis
    }

    @GetMapping("/redisConnectionFactoryTest")
    public void RedisConnectionFactoryTest() {
        RedisConnectionFactory redisConnectionFactoryBean = context.getBean(RedisConnectionFactory.class);
        log.debug(redisConnectionFactoryBean.toString()); // 结果： org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory@59496961
    }


    static long i = 20;
    static long sum = 300;

    //    ========================== String =======================
    @GetMapping("/set/{key}")
    public String s1(@PathVariable String key) {
        // 设置字符串
        RBucket<String> keyObj = redissonClient.getBucket(key);
        keyObj.set(key + "1-v1");
        return key;
    }

    @GetMapping("/get/{key}")
    public String g1(@PathVariable String key) {
        // 设置字符串
        RBucket<String> keyObj = redissonClient.getBucket(key);
        String s = keyObj.get();
        return s;
    }

    //    ========================== hash =======================-=

    @GetMapping("/hset/{key}")
    public String h1(@PathVariable String key) {

        Ur ur = new Ur();
        ur.setId(MathUtil.randomLong(1, 20));
        ur.setName(key);
        // 存放 Hash
        RMap<String, Ur> ss = redissonClient.getMap("UR");
        ss.put(ur.getId().toString(), ur);
        return ur.toString();
    }

    @GetMapping("/hget/{id}")
    public String h2(@PathVariable String id) {
        // hash 查询
        RMap<String, Ur> ss = redissonClient.getMap("UR");
        Ur ur = ss.get(id);
        return ur.toString();
    }

    // 查询所有的 keys
    @GetMapping("/all")
    public String all() {
        RKeys keys = redissonClient.getKeys();
        Iterable<String> keys1 = keys.getKeys();
        keys1.forEach(System.out::println);
        return keys.toString();
    }

    // ================== ==============读写锁测试 =============================

    @GetMapping("/rw/set/{key}")
    public void rw_set() {
//        RedissonLock.
        RBucket<String> ls_count = redissonClient.getBucket("LS_COUNT");
        ls_count.set("300", 360000000l, TimeUnit.SECONDS);
    }

    // 减法运算
    @GetMapping("/jf")
    public void jf() {

        String key = "S_COUNT";

//        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
//        atomicLong.set(sum);
//        long l = atomicLong.decrementAndGet();
//        System.out.println(l);

        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        if (!atomicLong.isExists()) {
            atomicLong.set(300l);
        }

        while (i == 0) {
            if (atomicLong.get() > 0) {
                long l = atomicLong.getAndDecrement();
                try {
                    Thread.sleep(1000l);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i--;
                System.out.println(Thread.currentThread().getName() + "->" + i + "->" + l);
            }
        }


    }

    @GetMapping("/rw/get")
    public String rw_get() {

        String key = "S_COUNT";
        Runnable r = new Runnable() {
            @Override
            public void run() {
                RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
                if (!atomicLong.isExists()) {
                    atomicLong.set(300l);
                }
                if (atomicLong.get() > 0) {
                    long l = atomicLong.getAndDecrement();
                    i--;
                    System.out.println(Thread.currentThread().getName() + "->" + i + "->" + l);
                }
            }
        };

        while (i != 0) {
            new Thread(r).start();
//            new Thread(r).run();
//            new Thread(r).run();
//            new Thread(r).run();
//            new Thread(r).run();
        }


        RBucket<String> bucket = redissonClient.getBucket(key);
        String s = bucket.get();
        System.out.println("================线程已结束================================" + s);

        return s;
    }

}
